#!/usr/bin/env python
#coding: utf8
#################################### IMPORTS ###################################

# Std Libs
import unittest
import functools
import sys
import os
import re
import pprint

from zencoding import zen_core

# PN modules
import pn, scintilla

##################################### DOCS #####################################

'''
High-level editor interface that communicates with underlying editor (like
Espresso, Coda, etc.) or browser.
Basically, you should call *set_context* method to
set up undelying editor context before using any other method.

This interface is used by <i>zen_actions.py</i> for performing different
actions like <b>Expand abbreviation</b>

@example
import zen_editor
zen_editor.set_context(obj);
//now you are ready to use editor object
zen_editor.get_selection_range();

@author Sergey Chikuyonok (serge.che@gmail.com)
@link http://chikuyonok.ru
'''

#################################### HELPERS ###################################


################################################################################

class ZenEditor():
    def __init__(self):
        pass

    def set_context(self, context):
        """
        Setup underlying editor context. You should call this method
        *before* using any Zen Coding action.
        @param context: context object
        """
        self.context = context
        self.sci = scintilla.Scintilla(context)

    def get_selection_range(self):
        """
        Returns character indexes of selected text
        @return: list of start and end indexes
        @example
        start, end = zen_editor.get_selection_range();
        print('%s, %s' % (start, end))
        """
        return self.sci.SelectionStart, self.sci.SelectionEnd

    def create_selection(self, start, end=None):
        """
        Creates selection from *start* to *end* character
        indexes. If *end* is ommited, this method should place caret
        and *start* index
        @type start: int
        @type end: int
        @example
        zen_editor.create_selection(10, 40)
        # move caret to 15th character
        zen_editor.create_selection(15)
        """
        self.sci.SetSelection(start, end or start)

    def get_current_line_range(self):
        """
        Returns current line's start and end indexes
        @return: list of start and end indexes
        @example
        start, end = zen_editor.get_current_line_range();
        print('%s, %s' % (start, end))
        """
        line = self.sci.LineFromPosition(self.sci.CurrentPos)
        return self.sci.PositionFromLine(line), self.sci.GetLineEndPosition(line)

    def get_caret_pos(self):
        """ Returns current caret position """
        return self.sci.CurrentPos

    def set_caret_pos(self, pos):
        """
        Set new caret position
        @type pos: int
        """
        self.create_selection(pos)

    def get_current_line(self):
        """
        Returns content of current line
        @return: str
        """
        return self.sci.GetCurLine()[0]

    def replace_content(self, value, start=None, end=None):
        """
        Replace editor's content or it's part (from *start* to
        *end* index). If *value* contains
        *caret_placeholder*, the editor will put caret into
        this position. If you skip *start* and *end*
        arguments, the whole target's content will be replaced with
        *value*.

        If you pass *start* argument only,
        the *value* will be placed at *start* string
        index of current content.

        If you pass *start* and *end* arguments,
        the corresponding substring of current target's content will be
        replaced with *value*
        @param value: Content you want to paste
        @type value: str
        @param start: Start index of editor's content
        @type start: int
        @param end: End index of editor's content
        @type end: int
        """
        if start is None: start = 0
        if end is None: end = self.sci.Length

        self.create_selection(start, end)
        
        # TODO: Need to make this use the templates stuff when PyPN supports it
        # For now, just use the first placeholder as a comment position
        value = re.sub(zen_core.get_caret_placeholder(), '', value)
        self.sci.ReplaceSel(value)

    def get_content(self):
        """
        Returns editor's content
        @return: str
        """
        return self.sci.GetText(self.sci.Length)

    def get_syntax(self):
        """
        Returns current editor's syntax mode
        @return: str
        """
        
        # TODO: Work out how to find out we're in CSS, see komodo or similar implementation.
        return 'html'

    def get_profile_name(self):
        """
        Returns current output profile name (@see zen_coding#setup_profile)
        @return {String}
        """
        return 'xhtml'
        
    def prompt(self, title):
        """
        Ask user to enter something
        @param title: Dialog title
        @type title: str
        @return: Entered data
        @since: 0.65
        """
        return pn.InputBox('Zen Coding', prompt)
        
    def get_selection(self):
        """
        Returns current selection
        @return: str
        @since: 0.65
        """
        return self.sci.SelText

    def get_file_path(self):
        """
        Returns current editor's file path
        @return: str
        @since: 0.65 
        """
        return self.context.FileName
#
#    def add_placeholders(self, text, selection=None):
#        _ix = [0]
#
#
#        def get_ix(m):
#            _ix[0] += 1
#            return '$%s' % _ix[0]
#
#        text = re.sub(r'\$', '\\$', text)
#        text = re.sub(zen_core.get_caret_placeholder(), get_ix, text)
#        
#        if selection:
#            # The last placeholder will contain the selected text, if any
#            text = re.sub('\$(%s)' % _ix[0], r'${\1:$SELECTION}', text)
#
#        return text